כל מה שצריך לדעת על החבאת הסיומת, על קישורים בעברית, על שִכתוב כתובות עם פרמטרים או סתם על איך ליצור קישורים יפים לעין ולמנועי החיפוש.
mod_rewrite
mod_rewrite זו הרחבה לשרת ה-Apache שמאפשרת לשרת לנתח את הכתובת המבוקשת ולהעביר את הבקשה לכתובת אחרת בתוך השרת, בלי שהלקוח ידע מזה. מבחוץ נראה שהשרת מקבל את הבקשה, מנתח אותה, מחליט אל מי להפנות אותה, עושה את הבקשה מעצמו אל עצמו אל הכתובת החדשה ומחזיר את התשובה מהכתובת המקורית.
את כללי שינוי הכתובת יש לרשום בקובץ הגדרות מיוחד שנקרא htaccess, שזה קובץ ללא שם עם סיומת htaccess. לא ניתן ליצור קובץ כזה דרך מערכת ההפעלה. יש לפתוח עורך טקסט ולבחור באפשרות "Save as" עם שם ריק וסיומת .htaccess.
דוגמה
.htaccess
RewriteEngine On
RewriteRule login login.php
RewriteRule contact_us index.php?action=contactus
RewriteRule login login.php
RewriteRule contact_us index.php?action=contactus
השורה הראשונה מפעילה את מנוע שִכתוב הכתובות.
כל פקודה מתחילה מהמילה RewriteRule – "כלל שכתוב", כאשר הכתובת שהשרת מצפה לקבל מופרדת ברווח מהכתובת שהשרת יבצע.
כשנגלוש אל http://example/login השרת יזהה את הכתובת login ויבצע את הבקשה כאילו הייתה אל http://example/login.php.
כשנגלוש אל http://example/contact_us השרת יזהה את כתובת הגלישה contact_us ויבצע את הבקשה כאילו הייתה http://example/index.php?action=contactus.
ביטויים רגולריים
mod_rewrite מבוסס על ביטויים רגולריים כדי לנתח את הבקשה. כלי חזק לניתוח הבקשות עומד לרשותנו, או לפחות לרשות מי שקרא על ביטויים רגולריים. :)
דוגמה
.htaccess
RewriteEngine On
RewriteRule user/([a-z0-9_]+) index.php?action=showUserInfo&username=$1
RewriteRule ([0-9_]+)\.html page.php?id=$1
RewriteRule user/([a-z0-9_]+) index.php?action=showUserInfo&username=$1
RewriteRule ([0-9_]+)\.html page.php?id=$1
הקוד הראשון מחפש בקשות שמתחילות במילה user ואחריה שם משתמש. לדוגמה, גלישה לעמוד http://example/user/alex תתבצע כאילו גלשנו אל http://example/index.php?action=showUserInfo&username=alex.
הקוד השני הופך את כל הקישורים בסגנון http://example/מספר.html כאילו גלשנו אל http://example/page.php?id=מספר.
דגלים
דגלים מסמנים לשרת אופציות מיוחדות עבור אותו כלל שכתוב.
NC – no case
לפי ברירת המחדל התנאים רגישים לאותיות רישיות. כלומר, התנאי עם הכתובת user יעבוד אם נגלוש אל user, ולא יעבוד עם נגלוש ל-UsEr, למשל.
כדי לומר לתנאים לא להתייחס לגודל האותיות נשתמש ב-flag באופן הבא:
RewriteRule user/([a-z0-9_]+) user.php?name=$1 [NC]
QSA – Query String Append
בגלל שהשרת כביכול מעביר בקשה חדשה בהתאם לשכתוב – הפרמטרים בכתובת עשויים להיעלם. הדגל QSA דואג לשמר את הפרמטרים בכתובת.
למשל:
RewriteRule alex index.php?action=alex [QSA]
כשנגלוש אל http://example/alex?blabla=true&blibli=win הפרמטרים יישמרו, והבקשה תועבר אל
http://example/index.php?action=alex&blabla=true&blibli=win.
L – Last
לכתובת http://example.com/abcmus יכולים להתאים כמה תנאים במקביל.
RewriteEngine On
RewriteRule a index.php?action=a
RewriteRule ab index.php?action=ab
RewriteRule abc index.php?action=abc
RewriteRule a index.php?action=a
RewriteRule ab index.php?action=ab
RewriteRule abc index.php?action=abc
abcmus מתאימה לכל שלושת התנאים. השרת יעבור תנאי אחר תנאי ויבדוק אותם. התנאי האחרון שיתאים לו – הוא זה שישתמש בו. כלומר, abcmus יפנה אל action=abc.
על מנת למנוע מהשרת להמשיך את הבדיקה ברגע שתנאי מסוים תואם, ולא להמשיך בכל זאת לעבור תנאי אחר תנאי – נשתמש בדגל Last. כלומר, אם התנאי התאים – תנצל אותו ואל תבדוק תנאים אחרים.
RewriteEngine On
RewriteRule a index.php?action=a [L]
RewriteRule ab index.php?action=ab [L]
RewriteRule abc index.php?action=abc [L]
RewriteRule a index.php?action=a [L]
RewriteRule ab index.php?action=ab [L]
RewriteRule abc index.php?action=abc [L]
ברגע שתנאי a התאים, לא תתבצע בדיקה של שאר התנאים, והשרת יעשה את הפעולה שלו.
לחבר דגלים
לחבר מספר דגלים עבור אותו תנאי אפשר באמצעות פסיקים.
ברוב המקרים כל התנאים שלכם יכילו בדיוק את שלושת הדגלים האלו באופן הבא:
RewriteRule alex index.php?act=alex [L,NC,QSA]
טיפים
RewriteRule a index.php?action=a
זהו תנאי גרוע, כי הביטוי הרגולרי תואם לכל הכתובות שבהם קיימת האות a. גם abcmus, גם blabla וגם odktnsqhjstnkhthqjskthA.html.
זוכרים למה? למדנו ביטויים רגולריים. השתמשו ב-^$ לסימון תחילת וסוף מחרוזת.
500 Server Error
העתקתם את הדוגמה וקיבלתם שגיאת 500? הסיבה לכך היא שהרחבת ה-mod_rewrite כבויה.
בתפריט ה-Wamp מצאו תחת apache modules את mod_rewrite, סמנו לידו v והפעילו את השרת מחדש.
לבעלי שרתים משלהם – מצאו בקובץ httpd.conf את mod_rewrite והורידו את הנקודה-פסיק לפני ה-load_module. אחרי הפעלה מחודשת של השרת הכול יעבוד.
קבצים קיימים
ברוב המקרים, אם יש בקשה לקובץ קיים – style.css, למשל – אנחנו רוצים שהשרת פשוט יבצע את הבקשה בלי להתחיל לעבור את כל התנאים. שלושת השורות הבאות מצילות את המצב:
# If the file exists – proccess the file, if not – proccess other rules
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
(L) – אם הכתובת מובילה לקובץ קיים או שהיא שם של תיקיה קיימת, אזי לבצע את הבקשה הנוכחית כפי שהיא ולא להמשיך לעבור על תנאים אחרים.
את התנאי הזה יש לשים כתנאי הראשון מבין כל התנאים, כדי שהשרת יבדוק אותו קודם כול, ורק אם הוא לא מתאים (אם הבקשה היא לא לקובץ או לתיקייה מסוימים) – רק אז שימשיך הלאה.
קישורים בעברית
הדפדפנים והרשת כרגע לא יודעים להתמודד טוב מדי עם אותיות לא אנגליות בתוך הקישורים. כדי להקל עליהם – יש להשתמש בפונקציה urlencode על תוכן הקישורים כדי שהסימנים המוזרים והטקסט בעברית יקודדו באופן מסוים ויעברו ברשת בשלמותם. השרת ידאג לפענח את הקישורים חזרה לעברית תקינה. ראו דוגמה.
זהו זה, אתם מוכנים ליצור כתובות קצרות, יפות, שונות ומשונות כפי שבא לכם וכפי שהאתר הזה עושה.
ותתחילו מלהוריד את ה-www. ;-)
upd: טיפ שנותן yehudade בתגובות למטה: רצוי לשים את כל הקוד שלכם לתוך תנאי מסוים, כך שבמקרה שהשרת לא תומך ב-mod_rewrite והמודול לא מותקן - לא תקבלו הרבה שגיאות 500.
התנאי הפשוט IfModule:
<IfModule mod_rewrite.c>
...קוד שִכתוב...
</IfModule>
...קוד שִכתוב...
</IfModule>
זהו, אם המודול לא מופעל מאיזושהי סיבה – לפחות לא תופיעה שגיאה.
ככה למשל ייראה קוד לדוגמה יחד עם התנאי:
<IfModule mod_rewrite.c>
# If the file exists - proccess the file, if not proccess other rules
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
RewriteRule ^alex$ index.php?act=alex [L,NC,QSA]
RewriteRule ^John$ index.php?nhoj=tca [L,NC,QSA]
</IfModule>
# If the file exists - proccess the file, if not proccess other rules
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
RewriteRule ^alex$ index.php?act=alex [L,NC,QSA]
RewriteRule ^John$ index.php?nhoj=tca [L,NC,QSA]
</IfModule>
תגובות לכתבה:
מדריך מצויין.
רק בקטע של ה500, למיטב זכרוני זה לא נכון.
כאשר mod_rewrite כבוי, הוא בכלל לא ישים לב לקובץ hta ובכך גם לא יתן שגיאה. השגיאה קורת רק כשהמוד דלוק ויש שגיאה כלשהי בקובץ, לדוגמא RewriteRulezz x x.php
תודה, מדריך מצויין.
רק שאלה, זה עובד גם ב Wamp ?
תודה רבה!
המדריך מצויין, כל הכבוד.
ב wamp יש אפאצ'י שזה שרת לכל דבר.. אז כן.
כש mod_rewrite לא מופעל השרת לא יזהה את הפקודה RewriteEngine ויחזיר שגיאה בדיוק כפי שיחזיר אחת על פקודה אחת שהוא לא מזהה כמו RewriteRulez
צודק :-)
ההערה שהוספת בסוף ממש נכונה.
מדריך יפה, אהבתי
שאלה:
אני לא בטוח שהבנתי את הכל ולכן אני שואל
נניח יש לי אתר בשם http://example.com
משתמש גלש לאתר שלי בכותבת הבאה
http://example.com/index.php?action=15
אני רוצה שכל גלישה לאתר שלי לא משנה לאיזה
ספרייה נכנסים או איזה פרמטרים המשתמש שולח לי דרך כתובת האתר, אני רוצה שתמיד ובכל מצב בשורת הכתובת של המשתמש יהיה את שם הכתובת של הדומיין שלי
במיקרה הזה יהיה רשום
http://example.com
כיצד אני עושה את זה
תודה!
אי אפשר לעשות את זה בדרכים פשוטות. השרת צריך להבין מה אתה רוצה ממנו ואיזה סקריפט להפעיל. את ההבחנה הזו הוא עושה לפי הכתובת.
אמנם אתה יכול להגיד לו שבגלישה אל site.com/a הוא יפעיל את 1.php
ובגלישה אל site.com/b הוא יפעיל את 2.php
אבל אין לו דרך כל הזמן בגלישה אל site.com לנחש לבד מה אתה רוצה ממנו ופעם להפעיל את 1.php ופעם את 2.php
יש אפשרות ב HTACCESS לחסום גישה לקבצים בתיקיות אבל להשתמש בהם בעזרת ייבואם עם INCLUDE ב PHP ?
למשל גלשתי לכאן php.com/templates/header.php
וזה קובץ שמיובא עם INCLUDE לדף INDEX.PHP בתיקיית ROOT והוא מכיל נתונים שלא הייתי רוצה שהגולש יראה .
לאבטח את HEADER.PHP זה לא בעיה, אפשר עם PHP , אבל אני מחפש פתרון יותר יעיל , כלומר בקוד אחד
לחסום את הגישות לכל הקבצים בתיקיה TEMPLATES אבל לאפשר להפעיל אותם כאשר אני מייבא אותם לדפים בתיקיית ROOT .
אשמח לשמוע פתרונות ובכלל לדעת אם לאבטח ככה עם HTACCESS זה מספיק .
עוד שאלה : אםם אני חוסם גישה לקבצים בתיקיה TEMPLATES עם HTACCESS בלבד , אנשים יוכלו לייבא אותם
משרת אחר עם INCLUDE ובעצם לצפות בתוכנם או ש HTACCESS חוסם את הגישה אוטומטית כאשר אני מבקש את הדף ?
תודה מראש .
שים קובץ htaccess עם התוכן
deny from all
בתוך התיקיה שאליה לא אמורים לגלוש
ו apache לא תאפשר גישה לקובץ הזה דרכה
זה אומר שהסקריפט שלך יוכל לעשות לו אינקלוד (כי הסקריפט שלך ניגש ישירות לקובץ ולא מבקשה מ APACHE להחזיר את תוכן הקובץ)
לעשות אינקלוד לסקריפט משרת חיצוני אי אפשר בכלל, כי השרת מפעיל את הקוד ומחזיר למבקש את התוצאה, ולא את תוכן הקוד. deny all תחסום אפשרות זו ולא ניתן יהיה לקבל דרך apache גם לא את תוצאה הסקריפט.
מספיק טוב לאבטחה.
אחלה , תודה .
נגיד שעשיתי שכשנגלוש אל http://example/login השרת יזהה את כאילו הייתה אל http://example/login.php.
אבל אם משתמש כותב בשורת הכתובת http://example/login.php. מה יקרה?
הוא יגיעה אל אותו עמוד.
אפשר לחסום את זה, אבל בדרך כלל זה מיותר.
סתם כדי לדעת, איך עושים את זה?
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /[^?\ ]*\.php[/?\ ]
RewriteRule .*\.php$ 404.php [L]
יעביר את כל הבקשות שמסתיימות ב php. לעמוד 404.php
במקום הביטוי הרגולרי בשורה הראשונה אתה יכול לרשום גם שם של קובץ ספציפי.
תודה ;)
כשאני שם את ה QSA,זה פוגע לי באתר,וגורם לו להיראות רק טקסט (כאילו אין CSS).
כשאני נכנס לקובץ של ה CSS,אני לא רואה כרגיל את כל העיצוב,אלא דף ריק,אבל הוא לא ריק בשרת.
אפשר בבקשה עזרה?
הבעיה היא לא ב QSA אלה בשימוש ב-mod_rewrite עצמו.
ראה בפורום כאן: http://phpguide.co.il/forum/index.php/topic,596.0.html
ובבקשה להבא פנה עם שאלות לפורום.
יש לי בעיה עם המילה Letters
הקוד שלי הוא:
RewriteRule Letters letters.php
כשאני נכנס ל- localhost/Letters
זה מציג לי דף לבן ריק.
אם למשל אני הופך את האות הגדולה L לאות קטנה l,
אז זה עובד. ממה הבעיה יכולה לנבוע וכיצד ניתן לתקן זאת?
יש לי בקוד גם חלקים בעברית שעובדים מעולה, והקידוד הוא UTF-8. הכל מצוין חוץ מהמילה הזאת.
יכול להיות שהיא חלק משם של קובץ ארוך יותר או יש קובץ עם המילה הזאת בשם ומשהו בתחילת ה htaccess מפריע לו.
נסה ככה:
RewriteRule ^Letters$ letters.php
תודה על התגובה.
ניסיתי את הקוד הזה והוא גם לא עובד,
מכיוון שיש לי עוד קוד כזה רק בעברית, ניסיתי להכניס את הקוד האנגלי לקוד העברי, בצורה הבאה:
RewriteRule Letters|מכתבים letters.php
וזה עדיין לא עובד.
ובשביל להיות בטוח, השארתי רק את השורה:
RewriteRule ^Letters$ letters.php
כדי לוודא שאכן כלום לא מפריע.
אולי אפשרי להשתמש ב- urlencode ?
אפשר להשתמש בפורום, הוא יותר נוח לשיחה :)
+ תצרף את התוכן המלא של htaccess. יכול להיות שמשהו אחר מפריע לו
לא משנה, כבר הסתדרתי.
פשוט הייתה לי תיקייה עם אותו שם ששכחתי ממנה.
תודה רבה על ההסברים והידע :)
אני מתפלא שבכל השאלות והתשובות כאן לא ראיתי לרגע אחד את התנאי הפשוט IfModule
<IfModule mod_rewrite.c>
...קוד שיכתוב...
</IfModule>
וזהו, במידה ומסיבה כלשהי המודול לא מופעל לפחות לא תופיע שגיאה
תודה יהודה, הכתבה עודכנה :)
אני לא הצלחתי להבין משהוא, ובנוסף זה גם לא עובד לי.
מה שכן עובד זה שאם אני רושם Home זה שולח אותי לדף שביקשתי, אבל אם אני לוחץ על הלוגו ע"מ להגיע לאותה כתובת, אז הוא לא מראה לי בשורת הכתובת Home. שזה בעצם העניין של כל הסיפור הזה, לא?!
איך מקבלים יותר מפרמטר אחר כמו בדוגמא user
example.html/H/250/ybenDn/upload/DSC_00301.JPG/GETIMG.PHP
H-זה הפרמטר הראשון
250-זה השני
ybenDn/upload/DSC_00301.JPG-זה השלישי
http://phpguide.co.il/q358/איך מקבלים יותר מפרמטר אחד בקובץ htaccess.htm
איך אפשר לעשות שהוא יקבל כל תו?
לא משנה איזה?
לא משנה הצלחתי
עם קורה מצב שיש שתי כתבות באותו שם..?
וכם עם רוצים לעשות בכותרת סימן כמו +?
במקרה הראשון התנאי הראשון שיתאים לכתובת יפעל.
במקרה השני תוסיף לביטוי הרגולרי את הסימן +
למה הקוד הזה לא עובד לי?
RewriteRule page/([0-9]+)\.html$ index.php?page=$1^
יותר נכון יהיה לומר שהקוד כן עובד, אבל הוא מציג לי את הדף ללא CSS(הCSS נמצא בקובץ חיצוני) למה???
הרי זה אמור לעבוד בדיוק כמו הקןד הזה בכתבה:
RewriteRule user/([a-z0-9_]+) index.php?action=showUserInfo&username=$1
טוב הסתדרתי הייתה בעעיה עם הסלאש(*תודה ליעד)
היי- איך אני נותן כתובות בעברית, לא הצלחתי
לא הבנתי איך אני יכול להפוך את:
site.com/?page=show&action=id
ל:
site.com/show.id או site.com/show/id או משהו כזה.
כמובן שזה דוגמא :-)
לא משנה, הצלחתי :-)
משהו יודע איפה נמצא הקובץ .htaccess ב XAMPP